package com.hducms.cms.action.admin;

import static com.hducms.core.action.front.LoginAct.MESSAGE;
import static com.hducms.core.action.front.LoginAct.PROCESS_URL;
import static com.hducms.core.action.front.LoginAct.RETURN_URL;
import static com.hducms.core.service.AuthenticationService.AUTH_KEY;

import java.io.IOException;
import java.security.interfaces.RSAPrivateKey;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Random;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.bouncycastle.util.encoders.Hex;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.SingleMessage;
import com.gexin.rp.sdk.base.impl.Target;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.template.TransmissionTemplate;
import com.hducms.cms.entity.assist.Dynamic;
import com.hducms.cms.entity.front.PushMessageMEntity;
import com.hducms.cms.entity.main.CmsUser;
import com.hducms.cms.entity.main.CmsUserExt;
import com.hducms.cms.service.CmsLogService;
import com.hducms.cms.service.CmsUserExtService;
import com.hducms.cms.service.CmsUserService;
import com.hducms.cms.service.DynamicPasswordService;
import com.hducms.cms.web.CmsUtils;
//import com.hducms.cms.manager.main.CmsLogMng;
//import com.hducms.cms.manager.main.CmsUserMng;
import com.hducms.common.security.BadCredentialsException;
import com.hducms.common.security.DisabledException;
import com.hducms.common.security.UsernameNotFoundException;
import com.hducms.common.util.DynamicPasswordTool;
import com.hducms.common.util.GetuiPushKey;
import com.hducms.common.util.RSA;
import com.hducms.common.web.CookieUtils;
import com.hducms.common.web.RequestUtils;
import com.hducms.common.web.ResponseUtils;
import com.hducms.common.web.session.SessionProvider;
import com.hducms.core.entity.Authentication;
import com.hducms.core.entity.Config;
//import com.hducms.core.entity.Config.ConfigLogin;
import com.hducms.core.service.AuthenticationService;
import com.hducms.core.service.ConfigService;
//import com.hducms.core.service.ConfigMng;
import com.hducms.core.service.UnifiedUserService;
import com.hducms.core.web.WebErrors;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;
//import com.octo.captcha.service.CaptchaServiceException;
//import com.octo.captcha.service.image.ImageCaptchaService;

@Controller
public class CmsLoginAct {
	private static final Logger log = LoggerFactory
			.getLogger(CmsLoginAct.class);

	public static final String COOKIE_ERROR_REMAINING = "_error_remaining";

	@RequestMapping(value = "/login.do", method = RequestMethod.GET)
	public String input(HttpServletRequest request,
			HttpServletResponse response, ModelMap model) {
		String message = RequestUtils.getQueryParam(request, MESSAGE);
		String authId = (String) session.getAttribute(request, AUTH_KEY);
		if (authId != null) {
			// 存在认证ID
			Authentication auth = authMng.retrieve(authId);
			// 存在认证信息，且未过期
			if (auth != null) {
				return "index";
			}
		}
		RSA rsa = new RSA();
//		rsa.setRadamKey(RequestUtils.getIpAddr(request));
		writeCookieErrorRemaining(null, request, response, model);
		if (!StringUtils.isBlank(message)) {
			model.addAttribute(MESSAGE, message);
		}
//		model.addAttribute("modouls","11");
//		model.addAttribute("exponent","11");
//		session.setAttribute(request, response, "privateKey", "11");
		
		model.addAttribute("modouls",new String(Hex.encode(rsa.getDefaultPublicKey().getModulus().toByteArray())));
		model.addAttribute("exponent",new String(Hex.encode(rsa.getDefaultPublicKey().getPublicExponent().toByteArray())));
		session.setAttribute(request, response, "privateKey", rsa.getDefaultPrivateKey());
		return "login";
	}

	@RequestMapping(value = "/login.do", method = RequestMethod.POST)
	public String submit(String username, String password, String captcha, String message,
			String dynamicPassword,HttpServletRequest request, HttpServletResponse response,
			ModelMap model) {
		long a = System.currentTimeMillis();
		RSAPrivateKey privateKey = (RSAPrivateKey) session.getAttribute(request, "privateKey");
		if(privateKey == null){
			return "login";
		}
		RSA rsa = new RSA();
		rsa.setPrivateKey(privateKey);
		username = new StringBuffer(rsa.decryptString(username)).reverse().toString();
		password = new StringBuffer(rsa.decryptString(password)).reverse().toString();
		long b = System.currentTimeMillis();
		System.out.println("##########解密耗费时间：" + String.valueOf(b-a));
		
		Integer errorRemaining = unifiedUserMng.errorRemaining(username);
		
		//验证登陆表单
		WebErrors errors = validateSubmit(username, password, captcha,
				errorRemaining, request, response);
		
		//如果表单验证没有错误
		if (!errors.hasErrors()) {
			try {
				String ip = RequestUtils.getIpAddr(request);
				
				//认证身份，并且保存认证信息
				Authentication auth = authMng.login(username, password, ip,
						request, response, session);
				
				// 登录次数的更新！！！！！未完成数据更新~！似乎已经更新！！！！！
				cmsUserMng.updateLoginInfo(auth.getUserid(), ip);
				CmsUser user = cmsUserMng.findById(auth.getUserid());
				
				if (user.getIsDisabled()) {
					// 如果已经禁用，则退出登录。
					authMng.deleteById(auth.getAuthenticationId());
					session.logout(request, response);
					throw new DisabledException("user disabled");
				}
//				###########动态短信验证码部分
				if (dynamicPassword.length()!=6) {
					authMng.deleteById(auth.getAuthenticationId());
					session.logout(request, response);
					throw new DisabledException("dynamicPassword error");
				}
				Dynamic dynamic = new Dynamic();
				dynamic = dps.findByUserId(auth.getUserid());
				if (dynamic == null) {
					authMng.deleteById(auth.getAuthenticationId());
					session.logout(request, response);
					throw new DisabledException("dynamicPassword error");
				}
				Date dt = new Date();
				dt = new Timestamp(System.currentTimeMillis());
				Integer t1 = dt.getSeconds() + dt.getMinutes()*60;
				Integer t2 = dynamic.getCreatTime().getSeconds() + dynamic.getCreatTime().getMinutes()*60;
				Integer result = t1-t2;
				if (result>120 || !dynamic.getRandcode().equals(dynamicPassword)) {
					dps.deleteById(auth.getUserid());
					authMng.deleteById(auth.getAuthenticationId());
					session.logout(request, response);
					throw new DisabledException("dynamicPassword error");
				}
//				###################################################
				cmsLogMng.loginSuccess(request, user, "login.log.loginSuccess");
				removeCookieErrorRemaining(request, response);
				if(user!=null){
					//登录成功返回后台首页
					return "redirect:index.do";
				}else{
					return "redirect:login.do";
				}
			} catch (UsernameNotFoundException e) {
				//用户不存在
				errors.addErrorString(e.getMessage());
				cmsLogMng.loginFailure(request, "login.log.loginFailure",
						"username=" + username );
			} catch (BadCredentialsException e) {
				//认证出错
				errors.addErrorString(e.getMessage());
				cmsLogMng.loginFailure(request, "login.log.loginFailure",
						"username=" + username );
			} catch (DisabledException e) {
				//禁用账户
				errors.addErrorString(e.getMessage());
				cmsLogMng.loginFailure(request, "login.log.loginFailure",
						"username=" + username );
			}
		}
		// 登录失败
		writeCookieErrorRemaining(errorRemaining, request, response, model);
		errors.toModel(model);
		if (!StringUtils.isBlank(message)) {
			model.addAttribute(MESSAGE, message);
		}
		
		return input(request, response, model);
//		return "login";
	}

	@RequestMapping(value = "/logout.do")
	public String logout(HttpServletRequest request,HttpServletResponse response) {
		String authId = (String) session.getAttribute(request, AUTH_KEY);
		if (authId != null) {
			authMng.deleteById(authId);
			session.logout(request, response);
		}
		String processUrl = RequestUtils.getQueryParam(request, PROCESS_URL);
		String returnUrl = RequestUtils.getQueryParam(request, RETURN_URL);
		String view = getView(processUrl, returnUrl, authId);
		if (view != null) {
			return view;
		} else {
			return "redirect:login.do";
		}
	}
	
//	/**
//	 * 用于获取动态密码，默认密码保存时间为两分钟
//	 * @author simony
//	 * @param request
//	 * @param response
//	 */
//	@RequestMapping(value="/dynamicPassword.do",method = RequestMethod.POST)
//	public void dynamicPassword(HttpServletRequest request,HttpServletResponse response){
//		String username = request.getParameter("username");
//		CmsUser user =  cmsUserMng.findByUsername(username);
//		if (user == null) {
//			return;
//		}
//		Integer userId = user.getUserId();
//		String identifier="";
//		CmsUserExt userExt = cmsUserExtMng.findById(userId);
//		String mobile = userExt.getMobile();
//		if (mobile=="") {
//			
//		}
//		Date dt = new Date();
//		dt = new Timestamp(System.currentTimeMillis());//随机数种子
//		long seed = dt.getTime();
//		Random rd = new  Random();
//		rd.setSeed(seed);
//		Integer dypass = rd.nextInt(1000000);
//		System.out.println(dypass.toString());
//		try {
//			identifier = dpTool.sendSms(mobile, dypass.toString());
//			dt = new Timestamp(System.currentTimeMillis());//用于判别动态密码是否失效。
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		dps.deleteById(userId);
//		dps.save(userId,identifier,dypass.toString(),dt);
//	}
	/**
	 * 用于获取动态密码，默认密码保存时间为两分钟
	 * @author simony
	 * @param request
	 * @param response
	 */
	@RequestMapping(value="/dynamicPassword.do",method = RequestMethod.POST)
	public void dynamicPassword(HttpServletRequest request,HttpServletResponse response){
		String username = request.getParameter("username");
		CmsUser user =  cmsUserMng.findByUsername(username);
		if (user == null) {
			return;
		}
		Integer userId = user.getUserId();
		String identifier="";
		CmsUserExt userExt = cmsUserExtMng.findById(userId);
//		String mobile = userExt.getMobile();
//		if (mobile=="") {
//			
//		}
		Date dt = new Date();
		dt = new Timestamp(System.currentTimeMillis());//随机数种子
		long seed = dt.getTime();
		Random rd = new  Random();
		rd.setSeed(seed);
		Integer dypass = rd.nextInt(1000000);
		System.out.println(dypass.toString());
//		Long cId = Long.parseLong(user.getPushChannelId());
		if (user.getClientId()==null) {
			return;
		}
		try {
//			identifier = dpTool.sendSms(mobile, dypass.toString());
			geTuiPush(user.getClientId(),dypass.toString());
			dt = new Timestamp(System.currentTimeMillis());//用于判别动态密码是否失效。
		} catch (Exception e) {
			e.printStackTrace();
		}
		dps.deleteById(userId);
		dps.save(userId,identifier,dypass.toString(),dt);
	}

//	public void PushUnicastAndroidNotification(String uId,Long cId,String message) {
//
//        /*
//         * @brief 向Android端设备推送单播消息
//         * message_type = 1
//         * device_type = 3
//         */
//
//        // 1. 设置developer平台的ApiKey/SecretKey
//        String apiKey = "oTjIBpnO9dhNAG4PTHqqG1Eg";
//        String secretKey = "ITS8GMogO0zqeca6ZhGvte2jIrBL9Dil";
//        ChannelKeyPair pair = new ChannelKeyPair(apiKey, secretKey);
//
//        // 2. 创建BaiduChannelClient对象实例
//        BaiduChannelClient channelClient = new BaiduChannelClient(pair);
//
//        // 3. 若要了解交互细节，请注册YunLogHandler类
//        channelClient.setChannelLogHandler(new YunLogHandler() {
//            @Override
//            public void onHandle(YunLogEvent event) {
//                System.out.println(event.getMessage());
//            }
//        });
//
//        try {
//
//            // 4. 创建请求类对象
//            PushUnicastMessageRequest request = new PushUnicastMessageRequest();
//            request.setDeviceType(3);
//            request.setChannelId(cId);
//            request.setUserId(uId);
//
//            request.setMessageType(1);
//            request.setMessage("{\"title\":\"动态密码\",\"description\":\"" + message +"  \"}");
//
//            // 5. 调用pushMessage接口
//            PushUnicastMessageResponse response = channelClient
//                    .pushUnicastMessage(request);
//
////            Assert.assertEquals(1, response.getSuccessAmount());
//
//        } catch (ChannelClientException e) {
//            // 处理客户端错误异常
//            e.printStackTrace();
//        } catch (ChannelServerException e) {
//            // 处理服务端错误异常
//            System.out.println(String.format(
//                    "request_id: %d, error_code: %d, error_message: %s",
//                    e.getRequestId(), e.getErrorCode(), e.getErrorMsg()));
//        }
//
//    }
	
	public void geTuiPush(String CID,String msg) throws IOException{
		String appId = getuikey.getAppId();
		String appkey = getuikey.getAppkey();
		String master = getuikey.getMaster();
		String host = getuikey.getHost();
		IGtPush push = new IGtPush(host, appkey, master);
		push.connect();
		TransmissionTemplate template = makeTemplate(appId,appkey,"动态密码","此次登录的动态密码是" + msg + "有效期两分钟",msg,PushMessageMEntity.PASSWORD);
		SingleMessage message = new SingleMessage();
		message.setOffline(true);
		message.setOfflineExpireTime(24 * 3600 * 1000);
		message.setData(template);
		Target target = new Target();
		target.setAppId(appId);
		target.setClientId(CID);
		IPushResult ret = push.pushMessageToSingle(message, target);
		System.out.println(ret.getResponse().toString());
	}
//	public static LinkTemplate linkTemplateDemo(String appId,String appkey,String msg) {
//		LinkTemplate template = new LinkTemplate();
//		// 设置APPID与APPKEY
//		template.setAppId(appId);
//		template.setAppkey(appkey);
//		// 设置通知栏标题与内容
//		template.setTitle("动态密码");
//		template.setText(msg);
//		// 配置通知栏图标
//		template.setLogo("icon.png");
//		// 配置通知栏网络图标
//		template.setLogoUrl("");
//		// 设置通知是否响铃，震动，或者可清除
//		template.setIsRing(true);
//		template.setIsVibrate(true);
//		template.setIsClearable(true);
//		// 设置打开的网址地址
//		template.setUrl("http://www.baidu.com");
//		return template;
//	}
	public  TransmissionTemplate makeTemplate(String appId,String appkey,String title,String text,String content,int messageType) {
		TransmissionTemplate template = new TransmissionTemplate();
		template.setAppId(appId);
		template.setAppkey(appkey);
		template.setTransmissionType(2);
		PushMessageMEntity message = new PushMessageMEntity();
		message.setMessageType(messageType);
		message.setTitle(title);
		message.setText(text);
		message.setContent(content);
		template.setTransmissionContent(makePushContent(message));
		return template;
	}
//	public  NotificationTemplate NotificationTemplateDemo(String appId,String appkey,String msg,int messageType) {
//		NotificationTemplate template = new NotificationTemplate();
//		// 设置APPID与APPKEY
//		template.setAppId(appId);
//		template.setAppkey(appkey);
//		// 设置通知栏标题与内容
//		template.setTitle("动态密码");
//		template.setText(msg);
//		// 配置通知栏图标
//		template.setLogo("icon.png");
//		// 配置通知栏网络图标
//		template.setLogoUrl("");
//		// 设置通知是否响铃，震动，或者可清除
//		template.setIsRing(true);
//		template.setIsVibrate(true);
//		template.setIsClearable(true);
//		// 透传消息设置
//		template.setTransmissionType(2);
//		PushMessageMEntity message = new PushMessageMEntity();
//		message.setMessageType(messageType);
//		message.setContent("");
//		template.setTransmissionContent(makePushContent(message));
//		return template;
//	}
	public String makePushContent(Object object) {
		ObjectMapper objectMapper = new ObjectMapper();
		String msg = null;
		try {
			msg = objectMapper.writeValueAsString(object);
		} catch (JsonGenerationException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return msg;
	}
	
	private WebErrors validateSubmit(String username, String password,
			String captcha, Integer errorRemaining, HttpServletRequest request,
			HttpServletResponse response) {
		WebErrors errors = WebErrors.create(request);
		if (errors.ifOutOfLength(username, "username", 1, 100)) {
			return errors;
		}
		if (errors.ifOutOfLength(password, "password", 1, 32)) {
			return errors;
		}
		// 如果输入了验证码，那么必须验证；如果没有输入验证码，则根据当前用户判断是否需要验证码。
		if (!StringUtils.isBlank(captcha)
				|| (errorRemaining != null && errorRemaining < 0)) {
			if (errors.ifBlank(captcha, "captcha", 100)) {
				return errors;
			}
			try {
				if (!imageCaptchaService.validateResponseForID(session
						.getSessionId(request, response), captcha)) {
					errors.addErrorCode("error.invalidCaptcha");
					return errors;
				}
			} catch (CaptchaServiceException e) {
				errors.addErrorCode("error.exceptionCaptcha");
				log.warn("", e);
				return errors;
			}
		}
		return errors;
	}

	/**
	 * 获得地址
	 * 
	 * @param processUrl
	 * @param returnUrl
	 * @param authId
	 * @param defaultUrl
	 * @return
	 */
	private String getView(String processUrl, String returnUrl, String authId) {
		if (!StringUtils.isBlank(processUrl)) {
			StringBuilder sb = new StringBuilder("redirect:");
			sb.append(processUrl).append("?").append(AUTH_KEY).append("=")
					.append(authId);
			if (!StringUtils.isBlank(returnUrl)) {
				sb.append("&").append(RETURN_URL).append("=").append(returnUrl);
			}
			return sb.toString();
		} else if (!StringUtils.isBlank(returnUrl)) {
			StringBuilder sb = new StringBuilder("redirect:");
			sb.append(returnUrl);
			return sb.toString();
		} else {
			return null;
		}
	}

	/**
	 * @param userErrorRemaining
	 * @param request
	 * @param response
	 * @param model
	 */
	private void writeCookieErrorRemaining(Integer userErrorRemaining,
			HttpServletRequest request, HttpServletResponse response,
			ModelMap model) {
		// 所有访问的页面都需要写一个cookie，这样可以判断已经登录了几次。
		Integer errorRemaining = getCookieErrorRemaining(request, response);
		Integer errorInterval = configMng.getErrorInterval();
		if (userErrorRemaining != null
				&& (errorRemaining == null || userErrorRemaining < errorRemaining)) {
			errorRemaining = userErrorRemaining;
		}
		int maxErrorTimes = configMng.getErrorTimes();
		if (errorRemaining == null || errorRemaining > maxErrorTimes) {
			errorRemaining = maxErrorTimes;
		} else if (errorRemaining <= 0) {
			errorRemaining = 0;
		} else {
			errorRemaining--;
		}
		model.addAttribute("errorRemaining", errorRemaining);
		CookieUtils.addCookie(request, response, COOKIE_ERROR_REMAINING,
				errorRemaining.toString(), errorInterval * 60, null);
	}

	
	/**
	 * 删除错误记录Cookie
	 * @param request
	 * @param response
	 */
	private void removeCookieErrorRemaining(HttpServletRequest request,
			HttpServletResponse response) {
		CookieUtils.cancleCookie(request, response, COOKIE_ERROR_REMAINING,
				null);
	}

	/**
	 * @param request
	 * @param response
	 * @return
	 */
	private Integer getCookieErrorRemaining(HttpServletRequest request,
			HttpServletResponse response) {
		Cookie cookie = CookieUtils.getCookie(request, COOKIE_ERROR_REMAINING);
		if (cookie != null) {
			String value = cookie.getValue();
			if (NumberUtils.isDigits(value)) {
				return Integer.parseInt(value);
			}
		}
		return null;
	}

	@Autowired
	private CmsUserService cmsUserMng;
	@Autowired
	private UnifiedUserService unifiedUserMng;
	@Autowired
	private ConfigService configMng;
	@Autowired
	private AuthenticationService authMng;
	@Autowired
	private SessionProvider session;
	@Autowired
	private ImageCaptchaService imageCaptchaService;
	@Autowired
	private CmsLogService cmsLogMng;
	@Autowired
	private DynamicPasswordTool dpTool;
	@Autowired
	private DynamicPasswordService dps;
	@Autowired
	private CmsUserExtService cmsUserExtMng;
	@Autowired
	private GetuiPushKey getuikey;
}
